package com.itheima.stock.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.stock.entity.*;
import com.itheima.stock.mapper.*;
import com.itheima.stock.properties.MarketIndexProperties;
import com.itheima.stock.response.PageResult;
import com.itheima.stock.service.StockService;
import com.itheima.stock.util.DateTimeUtil;
import com.itheima.stock.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

@Service
public class StockServiceImpl implements StockService {

    private final StockRtInfoMapper stockRtInfoMapper;

    private final StockBlockRtInfoMapper stockBlockRtInfoMapper;

    private final StockMarketIndexInfoMapper marketMarketIndexInfoMapper;

    private final StockMarketLogPriceMapper marketMarketLogPriceMapper;

    private final MarketIndexProperties marketIndexProperties;

    private final StockBusinessMapper stockBusinessMapper;

    public StockServiceImpl (StockBusinessMapper stockBusinessMapper, MarketIndexProperties marketIndexProperties, StockMarketIndexInfoMapper marketMarketIndexInfoMapper, StockMarketLogPriceMapper marketMarketLogPriceMapper, StockBlockRtInfoMapper stockBlockRtInfoMapper, StockRtInfoMapper stockRtInfoMapper){
        this.stockBusinessMapper = stockBusinessMapper;
        this.marketIndexProperties = marketIndexProperties;
        this.marketMarketIndexInfoMapper = marketMarketIndexInfoMapper;
        this.marketMarketLogPriceMapper = marketMarketLogPriceMapper;
        this.stockBlockRtInfoMapper = stockBlockRtInfoMapper;
        this.stockRtInfoMapper = stockRtInfoMapper;
    }

    /**
     * 获取所有板块信息
     * @return
     */
    @Override
    public List<SectorAllVO> sectorAll() {

        // 交易时间和交易总金额降序查询，取前10条数据
        // 获取距离当前交易最近的一个时间
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());

        // todo mack data
        last = LocalDateTime.parse("2021-12-21 09:30:00" , DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        LocalDateTime begin = DateTimeUtil.getOpenDate(last);
        LocalDateTime end = DateTimeUtil.getCloseDate(last);

        // 根据时间进行查询 返回板块数据集合
        List<StockBlockRtInfo> blockRtInfoList = stockBlockRtInfoMapper.selectByDateTimeDesc(begin,end);

        // 返回数据
        return blockRtInfoList.stream().map((stockBlockRtInfo -> SectorAllVO.builder()
                .companyNum(stockBlockRtInfo.getCompanyNum())
                .tradeAmt(stockBlockRtInfo.getTradeAmount())
                .code(stockBlockRtInfo.getLabel())
                .avgPrice(stockBlockRtInfo.getAvgPrice())
                .name(stockBlockRtInfo.getBlockName())
                // todo yyyy-MM-dd -> yyyyMMdd 转换
                .curDate(stockBlockRtInfo.getCurTime().toLocalDate().toString())
                .tradeVol(stockBlockRtInfo.getTradeVolume())
                .updownRate(stockBlockRtInfo.getUpdownRate())
                .build())).toList();
    }

    /**
     * 获取所有涨幅信息
     * @return
     */
    @Override
    public List<IncreaseVO> getStockIncrease() {

        // 获取距离当前时间最近的股票交易时间
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());

        last = LocalDateTime.parse("2021-12-30 09:32:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 从数据库中获取当前这一分钟所有的股票信息
        List<StockRtInfo> stockRtInfoList = stockRtInfoMapper.selectByDateTimeDesc(last);

        List<IncreaseVO> result = new ArrayList<>();
        // 对数据进行运算处理
        stockRtInfoList.stream().forEach((stockRtInfo -> {
            IncreaseVO increaseVO = IncreaseVO.builder().build();
            // 向 VO 中添加数据
            increaseVO.setCode(stockRtInfo.getStockCode());
            increaseVO.setName(stockRtInfo.getStockName());
            increaseVO.setTradePrice(stockRtInfo.getCurPrice());
            increaseVO.setTradeAmt(stockRtInfo.getTradeAmount());
            increaseVO.setPreClosePrice(stockRtInfo.getPreClosePrice());
            increaseVO.setCurDate(stockRtInfo.getCurTime().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")));

            // 计算 涨幅
            BigDecimal upDown = (stockRtInfo.getCurPrice().subtract(stockRtInfo.getPreClosePrice())).divide(stockRtInfo.getPreClosePrice(),new MathContext(6)).multiply(new BigDecimal("1.0"));
            // 涨跌
            BigDecimal increase = stockRtInfo.getCurPrice().subtract(stockRtInfo.getPreClosePrice());
            // 振幅
            BigDecimal amplitude = (stockRtInfo.getMaxPrice().subtract(stockRtInfo.getMinPrice())).divide(stockRtInfo.getPreClosePrice(),new MathContext(6)).multiply(new BigDecimal("1.0"));

            increaseVO.setUpDown(upDown);
            increaseVO.setIncrease(increase);
            increaseVO.setAmplitude(amplitude);

            result.add(increaseVO);
        }));

        List<IncreaseVO> list = result.stream().sorted((o1, o2) -> o2.getUpDown().compareTo(o1.getUpDown())).limit(10).toList();

        return list;
    }

    @Override
    public StockUpDownVO<InfoVO> stockUpDown() {

        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());

        // todo mack data
        last = LocalDateTime.parse("2022-01-06 09:55:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        List<InfoVO> voList = stockRtInfoMapper.selectStockUpDown(last);

        // 定义区间顺序 -10~-7 -7~-5 -5~-3 -3~0 0~3 3~5 5~7 7~10
        List<String> range = Arrays.asList("-10~-7","-7~-5","-5~-3","-3~0","0~3","3~5","5~7","7~10");

        List<InfoVO> newArr = new ArrayList<>();

        range.forEach((rangeStr) -> {
            voList.forEach((infoVO) -> {
                if (rangeStr.equals(infoVO.getTitle())){
                    newArr.add(infoVO);
                }
            });
        });


        StockUpDownVO<InfoVO> build = StockUpDownVO.<InfoVO>builder()
                .infos(voList)
                .time(last.toString())
                .build();

        return build;
    }

    @Override
    public TradeAmtVO<OptionVO> tradeAmt() {
        // 模拟数据 T日 开始 2021-12-31 09:30:00 结束 2021-12-31 14:30:00
        // T-1日 开始 2021-12-30 9:30:00 结束 2021-12-31 14:30:00

        // 当前时间 T日
        LocalDateTime t = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        LocalDateTime t_open = DateTimeUtil.getOpenDate(t);
        LocalDateTime t_close = DateTimeUtil.getCloseDate(t);
        // 获取 T-1日
        LocalDateTime tMinusOne = DateTimeUtil.getPreviousTradingDay(t);
        LocalDateTime tMinusOne_open = DateTimeUtil.getOpenDate(tMinusOne);
        LocalDateTime tMinusOne_close = DateTimeUtil.getCloseDate(tMinusOne);

        // 使用模拟数据
        t_open = LocalDateTime.parse("2021-12-28 09:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        t_close = LocalDateTime.parse("2021-12-28 14:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        tMinusOne_open = LocalDateTime.parse("2021-12-27 09:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        tMinusOne_close = LocalDateTime.parse("2021-12-27 14:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        List<String> ids = marketIndexProperties.getInner();

        List<OptionVO> list = marketMarketIndexInfoMapper.selectTradeCount(tMinusOne_open,t_close,ids);

        LocalDate tDate = t_open.toLocalDate();
        LocalDate tMinusOneDate = tMinusOne_open.toLocalDate();
        List<OptionVO> tList = list.stream().filter((vo) -> {
            LocalDateTime parse = LocalDateTime.parse(vo.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            LocalDate targetDate = parse.toLocalDate();
            return targetDate.isEqual(tDate);
        }).toList();
        List<OptionVO> tMinusOneList = list.stream().filter((vo) -> {
            LocalDateTime parse = LocalDateTime.parse(vo.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            LocalDate targetDate = parse.toLocalDate();
            return targetDate.isEqual(tMinusOneDate);
        }).toList();
        return TradeAmtVO.<OptionVO>builder()
                .volList(tList)
                .yesVolList(tMinusOneList)
                .build();
    }

    /**
     * 统计涨停和跌停的股票数据
     * @return
     */
    @Override
    public UpDownVO<OptionVO> upDown() {
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());

        // 定义开始时间
        LocalDateTime begin = LocalDateTime.parse("2022-01-06 09:25:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 定义结束时间
        LocalDateTime end = LocalDateTime.parse("2022-01-06 14:25:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 获取涨停的股票数据
        List<OptionVO> upList = stockRtInfoMapper.selectUpOrDown(begin,end,true);
        // 获取跌停的股票数据
        List<OptionVO> downList = stockRtInfoMapper.selectUpOrDown(begin,end,false);

        return UpDownVO.<OptionVO>builder()
                .upList(upList)
                .downList(downList)
                .build();
    }

    /**
     * 获取所有股票信息
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult<MoreVO> getStockAll(Integer page, Integer pageSize) {

        var ref = new Object() {
            LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        };

        ref.last = LocalDateTime.parse("2021-12-30 09:32:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 使用pagehelper分页插件

        Page<MoreVO> result = PageHelper.startPage(page, pageSize).doSelectPage(() -> {
            List<MoreVO> moreVOList = stockRtInfoMapper.selectMore(ref.last);
        });

        return PageResult.<MoreVO>builder()
                .size(result.size())
                .totalRows(result.getTotal())
                .pageNum(result.getPageNum())
                .pageSize(result.getPageSize())
                .totalPages(result.getPages())
                .rows(result.getResult())
                .build();
    }

    /**
     * 获取所有股票经营业务信息列表
     * @return
     */
    @Override
    public List<StockBusiness> getStockBusiness() {
        return stockBusinessMapper.selectAll();

    }

    /**
     * 获取所有股票大盘信息
     * @return
     */
    @Override
    public List<MarketIndexVO> innerIndexAll() {
        // 获取上证和深证指数大盘编码
        List<String> ids = marketIndexProperties.getInner();
        // 获取距离当前时间最近的股票交易时间
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        // mock data 模拟数据
        String mockDate = "20211226105600";
        last = LocalDateTime.parse(mockDate, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

        // 查询数据库
        // 根据大盘编码和指定时间查询大盘指数信息
        List<StockMarketIndexInfo> stockMarketIndexInfosList = marketMarketIndexInfoMapper.selectByIdsAndTime(ids, last);
        // 根据大盘编码和指定日期查询大盘指数交易日志
        List<StockMarketLogPrice> stockMarketLogPricesList =marketMarketLogPriceMapper.selectByIdsAndDate(ids, last);

        //组装数据
        return stockMarketIndexInfosList.stream().map((info) -> {
            MarketIndexVO vo = MarketIndexVO.builder().build();
            vo.setCode(info.getMarkId());
            vo.setName(info.getMarkName());
            vo.setCurDate(info.getCurTime().toLocalDate().toString());
            vo.setTradeAmt(info.getTradeAccount());
            vo.setTradeVol(info.getTradeVolume());
            vo.setTradePrice(info.getCurrentPrice());
            vo.setUpDown(info.getUpdownRate());
            stockMarketLogPricesList.forEach((logPrice) -> {
                if (info.getMarkId().equals(logPrice.getMarketCode())) {
                    vo.setPreClosePrice(logPrice.getPreClosePrice());
                    vo.setOpenPrice(logPrice.getOpenPrice());
                } else {
                    vo.setOpenPrice(BigDecimal.ZERO);
                    vo.setPreClosePrice(BigDecimal.ZERO);
                }
            });
            return vo;
        }).toList();
    }
}
